#ifndef _FMVC_QUERY_PARAMS_
#define _FMVC_QUERY_PARAMS_

#include <fcgiapp.h>

#include <iostream>
#include <sstream>
#include <string>
#include <vector>

#include <boost/unordered_map.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/regex.hpp>
#include <boost/lexical_cast.hpp>

#include "Exceptions.h"

namespace FMVC
{
  class QueryParams
  {
    typedef boost::unordered_map<std::string,std::string> map;
    map _queryParamsMap;
  
    class Unescape
    {
      public:
      std::string operator()(boost::smatch const &what) 
      { 
        std::string matched = what[1].str();
        int v;
        std::stringstream s;
        s << std::hex << matched;
        s >> v;
        return boost::lexical_cast<std::string>((char)v);
      };

    };

    public:
    QueryParams(const std::string& queryString)
    {
      std::vector<std::string> vecParams;
      boost::split(vecParams,queryString,boost::is_any_of("&"));

      for (size_t i = 0 ; i < vecParams.size(); ++i)
      {
        size_t eqPosition;
        if ( (eqPosition = vecParams[i].find("=")) == std::string::npos )
          continue;

        std::string key,value;

        key = vecParams[i].substr(0,eqPosition);
        value = vecParams[i].substr(eqPosition+1);
        
        boost::regex r("%(..)");
        Unescape u;
        key = boost::regex_replace(key,r,u);
        value = boost::regex_replace(value,r,u);

        _queryParamsMap[key] = value;
      }
    }

    std::string Get(const std::string& key) const
    {
      try
      {
        std::string value = _queryParamsMap.at(key);
        return value;      
      }
      catch (std::out_of_range)
      {
        throw KeyNotFoundInQueryString(__FILE__,__LINE__,key);
      }
    }
  };
};
#endif
